import 'dart:async';

import 'package:bluetooth_protocols_parser_plugin/src/lorin/cmd/rs_jet_cmd.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/integrated/rs_jet_integrated_product_info.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/lorin_protocol.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/realtime/battery/rs_jet_realtime_battery_info.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/realtime/error/rs_jet_realtime_error.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/realtime/info/rs_jet_realtime_info.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/realtime/info/rs_jet_reatime_all_info.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/realtime/status/rs_jet_realtime_status.dart';
import 'package:bluetooth_protocols_parser_plugin/src/response/lorin_response_data.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/settings/rs_jet_settings.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/statistics/rs_jet_statistics_once_data.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/statistics/rs_jet_statistics_total_data.dart';
import 'package:bluetooth_protocols_plugin/library.dart';

import '../../enum/target_device_type.dart';
import '../integrated/rs_jet_integrated_realtime_info.dart';
import '../lorin_helper.dart';

class RsJetProtocol extends LorinProtocol<
    RsJetRealtimeInfo,
    RsJetRealtimeStatus,
    RsJetRealtimeError,
    RsJetRealtimeAllInfo,
    RsJetRealtimeBatteryInfo,
    RsJetStatisticsOnceData,
    RsJetStatisticsTotalData,
    RsJetSettings,
    RsJetIntegratedProductionInfo,
    RsJetIntegratedRealtimeInfo,
    LorinResponseData> {
  @override
  LorinPrivateIntructionMessage get privateInstrMessage =>
      _RsJetPrivateIntructionMessage();

  //
  // 蓝牙主动响应监听
  StreamSubscription? _bluetoothNotifyStreamSubscription;

  @override
  Future<RsJetRealtimeInfo> getRealtimeInfo() {
    return sendRequest(privateInstrMessage.getRealtimeInfoIntrMsg().toBytes())
        .then((rspMsg) {
      LorinMessage msg = LorinMessage.fromList(rspMsg);
      if (msg.data?.para == null) {
        throw Exception('Get RsJetRealtimeInfo failed');
      }
      return RsJetRealtimeInfo.fromBytes(msg.data!.para!);
    });
  }

  @override
  Future<RsJetRealtimeStatus> getRealtimeStatus() {
    return sendRequest(privateInstrMessage.getRealtimeStatusIntrMsg().toBytes())
        .then((rspMsg) {
      LorinMessage msg = LorinMessage.fromList(rspMsg);
      if (msg.data?.para != null) {
        return RsJetRealtimeStatus.fromBytes(msg.data!.para!);
      }
      throw Exception('Get RsJetRealtimeStatus failed');
    });
  }

  @override
  Future<RsJetRealtimeError> getRealtimeError() {
    return sendRequest(privateInstrMessage.getRealtimeErrorIntrMsg().toBytes())
        .then((rspMsg) {
      LorinMessage msg = LorinMessage.fromList(rspMsg);
      if (msg.data?.para != null) {
        return RsJetRealtimeError.fromBytes(msg.data!.para!);
      }
      throw Exception('Get RsJetRealtimeError failed');
    });
  }

  @override
  Future<RsJetRealtimeAllInfo> getRealtimeAll() {
    return sendRequest(privateInstrMessage.getRealtimeAllIntrMsg().toBytes())
        .then((rspMsg) {
      LorinMessage msg = LorinMessage.fromList(rspMsg);
      if (msg.data?.para != null) {
        return RsJetRealtimeAllInfo.fromBytes(msg.data!.para!);
      }
      throw Exception('Get RsJetRealtimeAllInfo failed');
    });
  }

  @override
  Future<RsJetSettings> getSettingsAll() {
    return sendRequest(privateInstrMessage.getSettingsAllIntrMsg().toBytes())
        .then((rspMsg) {
      LorinMessage msg = LorinMessage.fromList(rspMsg);
      if (msg.data?.para != null) {
        return RsJetSettings.fromBytes(msg.data!.para!);
      }
      throw Exception('Get RsJetSettings failed');
    });
  }

  @override
  Future<RsJetStatisticsOnceData> getStatisticOnce(
      {int? startIndex, int? count}) {
    return sendRequest(privateInstrMessage
            .getStatisticOnceIntrMsg(startNum: startIndex, count: count)
            .toBytes())
        .then((rspMsg) {
      LorinMessage msg = LorinMessage.fromList(rspMsg);
      if (msg.data?.para != null) {
        return RsJetStatisticsOnceData.fromBytes(msg.data!.para!);
      }
      throw Exception('Get RsJetStatisticsOnceData failed');
    });
  }

  @override
  Future<RsJetStatisticsTotalData> getStatisticsTotal() {
    return sendRequest(
            privateInstrMessage.getStatisticsTotalIntrMsg().toBytes())
        .then((rspMsg) {
      LorinMessage msg = LorinMessage.fromList(rspMsg);
      if (msg.data?.para != null) {
        return RsJetStatisticsTotalData.fromBytes(msg.data!.para!);
      }
      throw Exception('Get RsJetStatisticsTotalData failed');
    });
  }

  @override
  Future<RsJetRealtimeBatteryInfo> getRealtimeBatteryInfo() {
    return sendRequest(
            privateInstrMessage.getRealtimeBatteryInfoIntrMsg().toBytes())
        .then((rspMsg) {
      LorinMessage msg = LorinMessage.fromList(rspMsg);
      if (msg.data?.para != null) {
        return RsJetRealtimeBatteryInfo.fromBytes(msg.data!.para!);
      }
      throw Exception('Get RsJetRealtimeBatteryInfo failed');
    });
  }

  @override
  Future<RsJetIntegratedProductionInfo> getIntegratedProductInfo() {
    throw UnimplementedError();
  }

  @override
  Future<RsJetIntegratedRealtimeInfo> getIntegratedRealtimeInfoAll() {
    throw UnimplementedError();
  }

  @override
  void cancelBluetoothNotifyStream() {
    _bluetoothNotifyStreamSubscription?.cancel();
    _bluetoothNotifyStreamSubscription = null;
  }

  @override
  void listenBluetoothNotifyStream(
      {Function(LorinResponseData p1)? callbackNfcCardPairSuccess,
      Function(RsJetRealtimeInfo p1)? callbackRealtimeInfo,
      Function(RsJetIntegratedRealtimeInfo p1)? callbackRealtimeAllInfo}) {
    _bluetoothNotifyStreamSubscription?.cancel();
    _bluetoothNotifyStreamSubscription = responseNotifyStream?.listen((data) {
      LorinMessage? lorinMessages = LorinHelper.bytesToLorinMessage(data);
      if (lorinMessages != null &&
          lorinMessages.data != null &&
          callbackRealtimeAllInfo != null) {
        callbackRealtimeAllInfo(RsJetIntegratedRealtimeInfo.fromBytes(
            lorinMessages.data!.toBytes()));
      }
    });
  }
}

class _RsJetPrivateIntructionMessage extends LorinPrivateIntructionMessage {
  @override
  get privateRequestBody => _RsJetPrivateRequestBody();
}

class _RsJetPrivateRequestBody extends LorinPrivateRequestBody {
  @override
  LorinCmdBase get cmdBase => RsJetCmd();

  @override
  int get defaultTargetDevice => TargetDeviceType.scooterDriver.rawValue;
}
